import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:myturngame/Theme.dart';
import 'package:myturngame/bean/combat/damage.dart';
import 'package:myturngame/bean/passive_effect.dart';
import 'package:myturngame/bean/role_in_combat.dart';
import 'package:myturngame/bean/skill/skill.dart';
import 'package:myturngame/common/game_global.dart';
import 'package:myturngame/state/SelectSkillChangeNotifier.dart';
import 'package:myturngame/utils/list_extend.dart';
import 'package:myturngame/widget/combat/dialog_skill_command.dart';
import 'package:myturngame/widget/text_decoration.dart';
import 'package:provider/provider.dart';

import '../../bean/combat/combat_action.dart';
import '../../bean/role_in_map.dart';
import '../../facotry/enemy_factory.dart';
import '../../facotry/reward_factory.dart';
import '../combat/fight_role_widget.dart';

///战斗界面
class CombatLayout extends StatefulWidget {
  //即将对战的敌人
  List<RoleInCombat?> enemyList = List.filled(10, null, growable: false);
  List<RoleInCombat?> usList = List.filled(10, null, growable: false);

  RoleInMap roleInMap;

  Function combatEndCallback;

  CombatLayout(this.roleInMap, this.combatEndCallback, {Key? key})
      : super(key: key) {
    //生成战斗队伍
    createCombatEnemy(roleInMap, enemyList);
    if (GameGlobal.player.pet != null) {
      usList[2] = RoleInCombat(GameGlobal.player.pet!, 2, RoleInCombat.teamUs);
    }
    usList[7] = RoleInCombat(GameGlobal.player, 7, RoleInCombat.teamUs);
  }

  @override
  State<CombatLayout> createState() => _CombatLayoutState();
}

class _CombatLayoutState extends State<CombatLayout> {
  ///战斗阶段
  int combatStage = 0;

  //0 玩家分配指令
  final int stagePlayerAction = 0;

  //1 宠物分配指令
  final int stagePetAction = 1;

  //2 其他角色分配指令
  final int stageOthersAction = 2;

  ///战斗行为
  List<CombatAction> combatActionList = [];

  //等待选中目标的“法术”
  Skill? skillToFindTarget;

  @override
  void initState() {
    super.initState();

    debugPrint("玩家行动");
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> children = [];
    children.add(Align(
      alignment: Alignment.center,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          rolesLayout(widget.enemyList.sublist(0, 5)),
          const SizedBox(height: 30),
          rolesLayout(widget.enemyList.sublist(5, 10)),
          const SizedBox(height: 130),
          rolesLayout(widget.usList.sublist(0, 5)),
          const SizedBox(height: 30),
          rolesLayout(widget.usList.sublist(5, 10)),
        ],
      ),
    ));

    debugPrint("视图构建:combatStage:${combatStage}");
    if (combatStage <= 1) {
      children.add(Align(
        alignment: Alignment.centerRight,
        child: Padding(
          padding: const EdgeInsets.only(top: 540, right: 10),
          child: commandLayout(),
        ),
      ));
    } else if (combatStage == 2) {
      //战斗中
      children.add(const Align(
        alignment: Alignment.center,
        child: Text("战斗中", style: textStyle),
      ));
    }

    // 当前指令状态
    children.add(Align(
      alignment: Alignment.center,
      child: Text(_stageText(), style: textStyle),
    ));

    return SizedBox(
      width: double.infinity,
      height: double.infinity,
      child: Center(
        child: Stack(
          children: children,
        ),
      ),
    );
  }

  Widget rolesLayout(List<RoleInCombat?> roles) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: roles.map((e) {
        //每个Item中间设置间距
        double right = 10;
        if (roles.last == e) {
          right = 0;
        }
        return Padding(
          padding: EdgeInsets.only(right: right),
          child: GestureDetector(
            onTap: () {
              //点击角色
              _dealRoleClick(e);
            },
            child: FightRoleLayout(e),
          ),
        );
      }).toList(),
    );
  }

  String _stageText() {
    if (combatStage == 0) {
      if (skillToFindTarget != null) {
        return "${skillToFindTarget?.name} 选择目标";
      } else {
        return "玩家分配指令";
      }
    } else if (combatStage == 1) {
      return "宠物分配指令";
    } else if (combatStage == 2) {
      return "战斗中";
    } else {
      return "未知";
    }
  }

  void _dealRoleClick(RoleInCombat? role) {
    if (role == null) {
      return;
    }
    if (combatStage == stagePlayerAction) {
      //无法点选友军
      if (widget.usList.contains(role)) {
        return;
      }
      if (skillToFindTarget != null) {
        _addSkillAction(skillToFindTarget!, widget.usList[7]!, role);
      } else {
        //添加玩家攻击行为
        _addAttackAction(widget.usList[7]!, role);
      }

      _nextState();
    } else if (combatStage == stagePetAction) {
      //无法点选友军
      if (widget.usList.contains(role)) {
        return;
      }
      //添加宠物攻击行为
      _addAttackAction(widget.usList[2]!, role);
      _nextState();
    }
  }

  Widget commandLayout() {
    String command = "";
    //指令集和
    List<String> commandList = [];
    if (combatStage == 0) {
      command = "玩家指令";
      commandList = ["自动", "法术", "逃跑"];
    } else {
      command = "宠物指令";
      commandList = ["自动", "法术", "返回"];
    }

    return BorderContainer(
      Row(
        children: [
          SizedBox(
            width: 20,
            height: 70,
            child: Text(command, style: textStyle4),
          ),
          Wrap(
            direction: Axis.vertical,
            spacing: 2,
            runSpacing: 2,
            children: commandList
                .map((e) => GestureDetector(
                      onTap: () {
                        _dealPlayerCommand(e);
                      },
                      child: BorderContainer(Text(e, style: textStyle2)),
                    ))
                .toList(),
          )
        ],
      ),
      width: 220,
      height: 90,
    );
  }

  ///处理玩家指令
  void _dealPlayerCommand(String command) {
    if (command == "逃跑") {
      _combatEscape();
    } else if (command == "返回") {
      setState(() {
        combatStage--;
      });
    } else if (command == "法术") {
      if (combatStage == stagePlayerAction) {
        showDialog(
            context: context,
            builder: (BuildContext context) {
              return DialogSkillCommand(() {
                setState(() {
                  skillToFindTarget = Provider.of<SelectSkillChangeNotifier>(
                          context,
                          listen: false)
                      .selectSkill;
                });
              });
            });
      }
    }
  }

  ///下一阶段
  void _nextState() async {
    setState(() {
      combatStage++;
    });
    //宠物行动阶段。如果没有出战宠物，直接跳过
    if (combatStage == stagePetAction) {
      debugPrint("宠物行动");
      if (widget.usList[2] == null) {
        combatStage++;
      }
    }
    //其他人行动阶段
    if (combatStage == stageOthersAction) {
      _othersAllotCommand();
      //结算战斗
      await _calculateCombat();

      Future.delayed(const Duration(milliseconds: 500), () {
        //TODO 本回合战斗结束
        setState(() {
          combatStage++;
        });
        //判断战斗是否结束
        var result = isCombatEnd();
        if (result == 0) {
          _newCombatRound();
        } else if (result == 1) {
          //战斗胜利
          _combatWin();
        } else {
          //战斗失败
          _combatLose();
        }
      });
    }
  }

  Future<void> delay(int milliseconds) async {
    await Future.delayed(Duration(milliseconds: milliseconds));
  }

  ///战斗是否结束
  ///0 未结束 1胜利 2失败
  int isCombatEnd() {
    if (widget.usList
        .every((element) => element == null || element.role.hp == 0)) {
      return 2;
    } else if (widget.enemyList
        .every((element) => element == null || element.role.hp == 0)) {
      return 1;
    } else {
      return 0;
    }
  }

  ///新的战斗回合
  void _newCombatRound() {
    debugPrint("新的回合");
    //重新标记可行动
    for (var element in widget.enemyList) {
      if (element != null) {
        element.isNotAllotCommand = true;
      }
    }
    //刷新
    setState(() {
      combatStage = 0;
    });
  }

  ///其他人分配指令
  void _othersAllotCommand() {
    debugPrint("其他人行动");
    for (var role in widget.usList) {
      if (role != null && role.isNotAllotCommand) {
        //在敌方阵营选一个角色攻击
        var target = widget.usList.randomNotNull();
        _addAttackAction(role, target);
      }
    }
    for (var role in widget.enemyList) {
      if (role != null && role.isNotAllotCommand) {
        var target = widget.usList.randomNotNull();
        _addAttackAction(role, target);
      }
    }
  }

  void _addAttackAction(RoleInCombat from, RoleInCombat target) {
    //标记为无法再行动
    from.isNotAllotCommand = false;
    _addCombatAction(AttackAction(from, target));
  }

  void _addCombatAction(CombatAction action) {
    combatActionList.add(action);
    if (action is HasTargetAction) {
      debugPrint(
          "action:${_indexAndName(action.from)} 对目标 ${_indexAndName(action.target)} 使用 ${action.name}");
    } else {
      debugPrint("action:${_indexAndName(action.from)} 使用 ${action.name}");
    }
  }

  _indexAndName(RoleInCombat role) =>
      "${role.teamStr()}${role.index}(${role.role.name})";

  ///结算战斗
  Future _calculateCombat() async {
    for (var action in combatActionList) {
      //需要角色可以行动
      if (action.from.canAction()) {
        if (action is HasTargetAction) {
          if (action.target.role.isDead()) {
            //目标已死亡，更换目标
            var newTargetRole = _changeTargetRole(action.target);
            //无可选目标，战斗结束
            if (newTargetRole == null) {
              return;
            } else {
              action.target = newTargetRole;
            }
          }
          //处理指令
          if (action is AttackAction) {
            await _dealAttackAction(action);
          } else if (action is SkillAction) {
            await _dealSkillAction(action);
          }
        }
      }
    }
    combatActionList.clear();
  }

  RoleInCombat? _changeTargetRole(RoleInCombat targetRole) {
    List<RoleInCombat?> sameTeam;
    //确定目标的敌对阵营
    if (targetRole.team == RoleInCombat.teamEnemy) {
      sameTeam = widget.enemyList;
    } else {
      sameTeam = widget.usList;
    }
    //确定活着的目标
    var liveRole =
        sameTeam.where((element) => element != null && element.role.isAlive());
    debugPrint("----- 活着的目标:${liveRole.length}");
    if (liveRole.isEmpty) {
      return null;
    } else {
      //随机一个
      return liveRole.elementAt(Random().nextInt(liveRole.length));
    }
  }

  ///胜利
  void _combatWin() {
    //结算奖励
    widget.combatEndCallback(createReward(widget.roleInMap));
    _resetCombatRole();
  }

  ///战斗失败
  void _combatLose() {
    widget.combatEndCallback(null);
    _resetCombatRole();
  }

  void _combatEscape() {
    widget.combatEndCallback(null);
    _resetCombatRole();
  }

  void _resetCombatRole() {
    for (int i = 0; i < 10; i++) {
      widget.enemyList[i] = null;
      widget.usList[i] = null;
    }
  }

  void _addSkillAction(Skill skill, RoleInCombat from, RoleInCombat target) {
    //标记为无法再行动
    from.isNotAllotCommand = false;
    _addCombatAction(SkillAction(from, target, skill));
  }

  Future _dealAttackAction(AttackAction action) async {
    //伤害不能低于1
    var damageValue = max(
        action.from.role.finalAttack() - action.target.role.finalDefend(), 1);
    var damage = _criticalAction(damageValue, action);
    _damageAddition(damage, action.from, action.target);
    await _dealCommonAction(action, damage, 1000);
    setState(() {
      action.target.damageListToShow.remove(damage);
    });
  }

  ///处理技能指令
  Future _dealSkillAction(SkillAction action) async {
    var skill = action.skill;
    if (skill is Skill001) {
      for (var damageRate in skill.damageRateList) {
        var damageValue = max(
            (action.from.role.finalAttack() -
                    action.target.role.finalDefend()) *
                damageRate ~/
                100,
            1);
        var damage = _criticalAction(damageValue, action);
        _damageAddition(damage, action.from, action.target);
        await _dealCommonAction(action, damage, 150);
      }
      await delay(500);
    } else if (skill is Skill002) {
      var damageValue = max(
          action.from.role.finalAttack() - action.target.role.finalDefend(), 1);
      //技能伤害加成
      damageValue = damageValue * 110 ~/ 100;
      //角色暴击率和技能暴击率合算
      var finalCritical =
          action.from.role.finalCriticalRate() + skill.criticalRate;
      var damage = _critical(
          damageValue, finalCritical, action.from.role.finalCriticalDamage())
        ..isSkillDamage = true;
      _damageAddition(damage, action.from, action.target);
      await _dealCommonAction(action, damage, 1000);
    }
    setState(() {
      action.target.damageListToShow.clear();
    });
  }

  ///伤害附加（流血）
  void _damageAddition(Damage damage, RoleInCombat from, RoleInCombat target) {
    for (List<PassiveEffect> effectList in from.role.effectMap.values) {
      for (PassiveEffect effect in effectList) {
        effect.effect(damage,target);
      }
    }
  }

  ///结算指令的暴击（封装了一下_critical）
  Damage _criticalAction(int damageValue, CombatAction action) {
    return _critical(damageValue, action.from.role.finalCriticalRate(),
        action.from.role.finalCriticalDamage());
  }

  ///结算暴击
  Damage _critical(int damageValue, int criticalRate, int criticalDamage) {
    var isCritical = _isCritical(criticalRate);
    if (isCritical) {
      damageValue = damageValue * criticalDamage ~/ 100;
    }
    return Damage(damageValue)..isCritical = isCritical;
  }

  bool _isCritical(int rate) => Random().nextInt(100) < rate;

  ///处理战斗行为的公共逻辑
  Future _dealCommonAction(
      HasTargetAction action, Damage damage, int attackDuration) async {
    //刷新
    setState(() {
      action.target.role.hp = max(action.target.role.hp - damage.finalValue(), 0);
      action.target.damageListToShow.add(damage);
      if (action.from.team == 1) {
        action.from.targetOffset = const Offset(0, 0.2);
      } else {
        action.from.targetOffset = const Offset(0, -0.2);
      }
    });
    debugPrint(
        "==${_indexAndName(action.from)} 攻击目标：${_indexAndName(action.target)} 造成 ${damage.finalValue()} 伤害");
    //延时
    await delay(attackDuration);
    setState(() {
      action.from.targetOffset = null;
    });
  }
}
